﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Common.Lib.Assembly
{
    public class AssemblyResourceCollection : ICollection<AssemblyResource>
    {

        protected List<AssemblyResource> _resources;
        protected string _assemblyName;

        public string AssemblyName { get { return _assemblyName; } }

        public AssemblyResourceCollection(string assemblyName, params string[] resPaths)
        {
            if (!IsAssemblyNameValid(assemblyName))
                throw new AssemblyResourceException("The given assembly name to create a AssemblyResourceColleciton is not valid");
            _assemblyName = assemblyName;
            _resources = new List<AssemblyResource>();

            AddRange(resPaths);
        }

        public AssemblyResourceCollection Add(AssemblyResource item)
        {
            string msg = null;
            if (!IsResourceValid(item, out msg))
                throw new AssemblyResourceException(msg + ", the AssemblyResource can not added in a AssemblyResourceColleciton");
            if (!Contains(item))
                _resources.Add(item);
            return this;
        }

        public AssemblyResourceCollection AddRange(IEnumerable<AssemblyResource> resList)
        {
            if (resList != null)
                foreach (var res in resList) 
                    Add(res);
            return this;
        }

        public AssemblyResourceCollection Add(string res)
        {
            AssemblyResource ar = new AssemblyResource(_assemblyName, res);
            Add(ar);
            return this;
        }

        public AssemblyResourceCollection AddRange(IEnumerable<string> resList)
        {
            if (resList != null && resList.Count() > 0)
            {
                AddRange(resList.Select(resName => new AssemblyResource(_assemblyName, resName)));
            }
            return this;

        }

        public void Clear()
        {
            _resources.Clear();
        }

        public bool Contains(AssemblyResource item)
        {
            foreach (var res in _resources)
            {
                if (res.Equals(item))
                    return true;
            }
            return false;
        }

        public void CopyTo(AssemblyResource[] array, int arrayIndex)
        {
            foreach (var res in _resources)
            {
                array.SetValue(res, arrayIndex++);
            }
        }

        public int Count
        {
            get 
            {
                return _resources.Count;
            }
        }

        public bool IsReadOnly
        {
            get { return false; }
        }

        public bool Remove(AssemblyResource item)
        {
            string msg = null;
            if (IsResourceValid(item, out msg))
                throw new AssemblyResourceException(msg + ", the AssemblyResource can not removed from a AssemblyCollection");

            if (Contains(item))
            {
                _resources.Remove(item);
                return true;
            }
            return false;
        }

        public IEnumerator<AssemblyResource> GetEnumerator()
        {
            return _resources.GetEnumerator();
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return _resources.GetEnumerator();
        }

        #region private

        

        private bool IsResourceValid(AssemblyResource item, out string msg)
        {
            msg = null;
            if (item == null) 
                msg = "The given AssemblyResource can not be null";
            if (string.IsNullOrWhiteSpace(item.AssemblyName)) 
                msg = "The AssemblyName of the given AssemblyResource can not be null";
            if (!_assemblyName.Equals(item.AssemblyName))
                msg = "The AssemblyName of the given AssemblyResource is not same with the current AssemblyResourceCollection";
            if (string.IsNullOrWhiteSpace(item.QualifiedResourcePath))
                msg = "The QualifiedResourcePath of the given AssemblyResource can not be null";

            if (msg == null) CheckResourceWithCustomConditions(item, out msg);
            return msg == null? true : false;
        }

        private bool IsAssemblyNameValid(string name)
        {
            bool valid = !string.IsNullOrWhiteSpace(name);
            if(valid)
                valid = CheckAssemblyNameWithCustomConditions(name);
            return valid;
        }

        protected virtual bool CheckAssemblyNameWithCustomConditions(string name)
        {
            return true;
        }

        protected virtual bool CheckResourceWithCustomConditions(AssemblyResource item, out string msg)
        {
            msg = null;
            return true;
        }
        #endregion private

        void ICollection<AssemblyResource>.Add(AssemblyResource item)
        {
            throw new NotImplementedException();
        }
    }
}
